import { Middleware, MiddlewareContext } from '../../core/types';

const activeRequests = new Map<string, number[]>();

export interface ThrottleOptions {
  limit?: number;
  interval?: number;
  getKey?: (ctx: MiddlewareContext) => string;
}

export function throttle(options: ThrottleOptions = {}): Middleware {
  const {
    limit = 5,
    interval = 1000,
    getKey = (ctx) => ctx.config.url || '',
  } = options;

  return async (ctx: MiddlewareContext, next) => {
    const key = getKey(ctx);
    const now = Date.now();

    if (!activeRequests.has(key)) {
      activeRequests.set(key, []);
    }

    const timestamps = activeRequests.get(key)!;

    // Clean up expired requests
    while (timestamps.length && now - timestamps[0] > interval) {
      timestamps.shift();
    }

    // If we've reached the limit, wait for the oldest request to expire
    if (timestamps.length >= limit) {
      const oldestTimestamp = timestamps[0];
      const timeToWait = interval - (now - oldestTimestamp);
      if (timeToWait > 0) {
        await new Promise((resolve) => setTimeout(resolve, timeToWait));
      }
      // Clean up expired requests after waiting
      const newNow = Date.now();
      while (timestamps.length && newNow - timestamps[0] > interval) {
        timestamps.shift();
      }
    }

    // Add current request timestamp
    const requestTime = Date.now();
    timestamps.push(requestTime);
    
    try {
      await next();
    } finally {
      // Remove the timestamp after request completes
      const index = timestamps.indexOf(requestTime);
      if (index !== -1) {
        timestamps.splice(index, 1);
      }
    }
  };
}
